package api

import (
	"archive/zip"
	"file_sys_server/serializer"
	"fmt"
	"io"
	"net/http"
	"os"
	"path"
	"strings"

	"github.com/gin-gonic/gin"
)

type Response struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
}

/*
*

	文件上传与下载
	文件转换成为对应的Bean类型

*
*/
func HandleUpLoadFile(c *gin.Context) {
	file, err := c.FormFile("file") // 字段form

	if err != nil {
		c.JSON(http.StatusOK, &Response{Code: 10002, Msg: "上传文件失败" + "file" + err.Error()})
		return
	}

	if strings.Contains(file.Filename, "xls") { // excel文件上传
		err = c.SaveUploadedFile(file, "./files/excels/"+file.Filename)
		if err != nil {
			c.JSON(http.StatusOK, &Response{Code: 10003, Msg: "服务端存储文件异常"})
			fmt.Println(err.Error())
			return
		}
	} else if strings.Contains(file.Filename, "pdf") { // pdf文件上传
		// 上传文档
		if strings.Contains(file.Filename, "使用说明") {
			err = c.SaveUploadedFile(file, "./files/inner_docs/"+file.Filename)
		} else {
			err = c.SaveUploadedFile(file, "./files/docs/"+file.Filename)
		}
		if err != nil {
			c.JSON(http.StatusOK, &Response{Code: 10003, Msg: "服务端存储t文件异常"})
			fmt.Println(err.Error())
			return
		}
	} else if strings.Contains(file.Filename, "mp4") || strings.Contains(file.Filename, "mov") { // mp4文件上传
		// 上传文档
		err = c.SaveUploadedFile(file, "./files/videos/"+file.Filename)
		if err != nil {
			c.JSON(http.StatusOK, &Response{Code: 10003, Msg: "服务端存储文件异常"})
			fmt.Println(err.Error())
			return
		}
	} else if strings.Contains(file.Filename, "apk") { // apk文件上传
		files, err := os.Open("./files/apks")
		if err != nil {
			c.JSON(http.StatusOK, &Response{Code: serializer.FileErr, Msg: "服务端存储文件异常"})
			fmt.Println(err.Error())
			return
		}
		defer files.Close()

		fileInfos, err := files.ReadDir(-1)
		if err != nil {
			c.JSON(http.StatusOK, &Response{Code: serializer.FileErr, Msg: "服务端存储文件异常"})
			fmt.Println(err.Error())
			return
		}

		// 找到之前上传的文件删除，只保留本次上传的记录
		for _, f := range fileInfos {
			if strings.Contains(f.Name(), "apk") {
				fmt.Println(f.Name())
				err = os.Remove("./files/apks/" + f.Name())
				if err != nil {
					fmt.Println("删除文件失败")
				}
			}
		}

		err = c.SaveUploadedFile(file, "./files/apks/"+file.Filename)
		if err != nil {
			c.JSON(http.StatusOK, &Response{Code: 10004, Msg: "服务端存储文件异常"})
			fmt.Println(err.Error())
			return
		}
	}

	c.JSON(http.StatusOK, &Response{Code: 10000, Msg: "上传文件成功"})

}

/*
*

	上传多个文件

*
*/
func HandleUploadMultiFiles(c *gin.Context) {
	err := c.Request.ParseMultipartForm(8 << 20) // 设置上传文档的最大内存 8Mb

	if err != nil {
		c.JSON(http.StatusOK, &Response{Code: 10001, Msg: "文件过大"})
		return
	}
	formdata := c.Request.MultipartForm
	files := formdata.File["file"]

	for _, file := range files {
		if strings.Contains(file.Filename, "xls") { // excel文件上传
			err = c.SaveUploadedFile(file, "./files/excels/"+file.Filename)
			if err != nil {
				c.JSON(http.StatusOK, &Response{Code: 10003, Msg: "服务端存储文件异常"})
				fmt.Println(err.Error())
				return
			}
		} else if strings.Contains(file.Filename, "apk") { // apk文件上传
			err = c.SaveUploadedFile(file, "./files/apks/"+file.Filename)
			if err != nil {
				c.JSON(http.StatusOK, &Response{Code: 10004, Msg: "服务端存储文件异常"})
				fmt.Println(err.Error())
				return
			}
		}
	}

	c.JSON(http.StatusOK, gin.H{"msg": "上传成功"})

}

/*
*

	下载文件

*
*/
func HandleDownloadFile(c *gin.Context) {
	// 打开文件
	filePath := c.Query("file_path")
	file, err := os.Open(filePath)
	if err != nil {
		c.JSON(http.StatusOK, &Response{Code: 10003, Msg: "服务端打开文件异常" + "file " + err.Error()})
		fmt.Println(err.Error())
		return
	}

	defer file.Close()

	// 设置响应头
	c.Header("Content-Type", "application/octet-stream")
	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", path.Base(filePath)))
	c.Header("Content-Transfer-Encoding", "binary")
	c.Header("Cache-Control", "no-cache")
	c.Header("Pragma", "no-cache")

	// 写入响应中
	c.File(filePath)
}

/*
下载多文件压缩包
*/
func HandleZipDownloadFile(c *gin.Context) {
	// 打开对应文件夹
	filePath := c.Query("file_path")
	dir, err := os.Open(filePath)
	if err != nil {
		c.JSON(http.StatusOK, &Response{Code: 10003, Msg: "服务端打开文件异常" + "dir: " + err.Error()})
		fmt.Println(err.Error())
		return
	}
	defer dir.Close()

	// 打开文件夹内的文件
	files, err := dir.Readdir(-1)
	if err != nil {
		c.JSON(http.StatusOK, &Response{Code: 10003, Msg: "服务端打开文件异常" + "files: " + err.Error()})
		fmt.Println(err.Error())
		return
	}
	//创建压缩文件
	zipFile := filePath + "/zipFile.zip"
	newZip, err := os.Create(zipFile)
	if err != nil {
		c.JSON(http.StatusOK, &Response{Code: serializer.FileErr, Msg: "服务端存储文件异常" + "zip: " + err.Error()})
		fmt.Println(err.Error())
		return
	}
	defer newZip.Close()

	// 开始压缩
	zipWriter := zip.NewWriter(newZip)

	// 逐个将文件进行复制，放入
	for _, f := range files {
		if f.IsDir() { // 如果是目录，就跳过
			continue
		}
		fmt.Println(f.Name())
		src, err := os.Open(filePath + "/" + f.Name())
		if err != nil {
			c.JSON(http.StatusOK, &Response{Code: serializer.FileErr, Msg: "服务端存储文件异常" + "src " + err.Error()})
			return
		}
		defer src.Close()

		w, err := zipWriter.Create(f.Name())
		if err != nil {
			c.JSON(http.StatusOK, &Response{Code: serializer.FileErr, Msg: "服务端存储文件异常" + "w " + err.Error()})
			return
		}

		_, err = io.Copy(w, src)
		if err != nil {
			c.JSON(http.StatusOK, &Response{Code: serializer.FileErr, Msg: "服务端存储文件异常" + "f " + err.Error()})
			return
		}
	}

	zipWriter.Close() // 在这里主动进行关闭，确保文件在传输之前全部刷入到文件中，避免文档缺失

	c.Header("Content-Type", "application/octet-stream")
	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", path.Base(zipFile)))
	c.Header("Content-Transfer-Encoding", "binary")
	c.Header("Cache-Control", "no-cache")
	c.Header("Pragma", "no-cache")

	c.File(zipFile)
	os.Remove(zipFile)
}

/*
*

	下载apk文件

*
*/
func HandleDownloadApkFile(c *gin.Context) {
	// 打开文件
	files, err := os.Open("./files/apks")
	if err != nil {
		c.JSON(http.StatusOK, &Response{Code: serializer.FileErr, Msg: "服务端存储文件异常"})
		fmt.Println(err.Error())
		return
	}
	defer files.Close()

	fileInfo, err := files.ReadDir(-1)
	if err != nil || len(fileInfo) != 1 {
		c.JSON(http.StatusOK, &Response{Code: serializer.FileErr, Msg: "服务端存储文件异常"})
		fmt.Println(err.Error())
		return
	}
	filePath := "./files/apks/" + fileInfo[0].Name()

	// 设置响应头
	c.Header("Content-Type", "application/octet-stream")
	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", path.Base(filePath)))
	c.Header("Content-Transfer-Encoding", "binary")
	c.Header("Cache-Control", "no-cache")
	c.Header("Pragma", "no-cache")

	// 写入响应中
	c.File(filePath)
}

// 测试服务启动
func HandleTest(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"msg": "ok"})
}
